//      fm.c
//      
//      Copyright 2011 DJ Shaji <djshaji@gmail.com>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.


#include "fm.h"

gint fm_sort_by_type ( GtkTreeModel * store, GtkTreeIter * iter1, GtkTreeIter * iter2 )
{
	gchar * name1 = null ;
	gchar * name2 = null ;
	
	gboolean is_dir1 = false, is_dir2 = false ;
	
	gtk_tree_model_get ( store, iter1, 2, & name1, -1 ) ;
	gtk_tree_model_get ( store, iter2, 2, & name2, -1 ) ;
	
	gint result = 0 ;
	if ( g_file_test ( name1, G_FILE_TEST_IS_DIR ) && g_file_test ( name2, G_FILE_TEST_IS_DIR ))
		result = fm_sort_func ( name1, name2 ) ;
	else if ( g_file_test ( name1, G_FILE_TEST_IS_DIR ) && ! g_file_test ( name2, G_FILE_TEST_IS_DIR ))
		result = -1 ;
	else if ( ! g_file_test ( name1, G_FILE_TEST_IS_DIR ) && ! g_file_test ( name2, G_FILE_TEST_IS_DIR ))
		result = 1 ;
	else
		result = fm_sort_func ( name1, name2 ) ;
	
	g_free ( name1 ) ;
	g_free ( name2 ) ;
	
	return result ;
}


GtkTreeModel * fm_create_store ( void )
{
	GtkListStore * store = gtk_list_store_new ( 3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING ) ;
	gtk_tree_sortable_set_default_sort_func ( store, fm_sort_by_type, null, null ) ;
	
	gtk_tree_sortable_set_sort_func ( store, 1, fm_sort_by_type, null, null ) ;
	gtk_tree_sortable_set_sort_column_id ( store, GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING ) ;
	
	return store ;
}

gint fm_sort_func ( gchar * data1, gchar * data2 )
{
	gint result = 0 ;
	gchar * basename1 = g_path_get_basename ( data1 ) ;
	gchar * basename2 = g_path_get_basename ( data2 ) ;
	
	gchar * name1 = g_utf8_strdown ( basename1, -1 ) ;
	gchar * name2 = g_utf8_strdown ( basename2, -1 ) ;
	
	gint len1 = strlen ( name1 ), len2 = strlen ( name2 ) ;
	gint i = 0, len = 0 ;
	if ( len2 < len1 )
		len = len2 ;
	else if ( len1 < len2 )
		len = len2 ;
	else if ( len1 == len2 )
		len = len1 ;
	
	for ( i = 0 ; i < len ; i ++ )
	{
		if ( name1 [i] < name2 [i] )
		{
			result = -1 ;
			break ;
		}
		else if ( name2 [i] < name1 [i] )
		{
			result = 1 ;
			break ;
		}
		else
			result = 0 ;
	}
	
	g_free ( name1 ) ;
	g_free ( name2 ) ;
	
	g_free ( basename1 ) ;
	g_free ( basename2 ) ;
	
	return result ;
}


void fm_open ( Explorer * e, gchar * folder )
{
	g_debug ( "Opening folder %s", folder ) ;
	
	if ( ! folder )
	{
		g_debug ( "%s: null pointer passed as argument for char !" ) ;
		return ;
	}
	
	GError * error = null ;
	GDir * dir = g_dir_open ( folder, 0, & error ) ;
	
	if ( dir == null )
	{
		g_warning ( "%s", error -> message ) ;
		return ;
	}
	
	explorer_wait_anim_start ( e ) ;
	
	GTimeVal tv ;
	g_get_current_time ( & tv ) ;
	
	glong timestamp = tv.tv_usec ;
	e -> timestamp = timestamp ;
	
	gtk_combo_box_append_text ( e -> addressbar_entry, folder ) ;
	gtk_combo_box_set_active ( e -> addressbar_entry, e -> counter ) ;
	
	e -> counter ++ ;
	
	gtk_window_set_title ( e -> window, folder ) ;
	explorer_set_status_message ( e, folder ) ;
	
	GtkTreeIter iter, reti ;
	if ( ! gtk_tree_model_get_iter_first ( e -> history_back, & reti ))
	{
		gtk_list_store_prepend ( e -> history_back, & iter ) ;
		gtk_list_store_set ( e -> history_back, & iter, 0, folder, -1 ) ;
	}	
	
	else
	{
		gchar * path = null ;
		gtk_tree_model_get ( e -> history_back, & reti, 0, & path, -1 ) ;
		
		if ( strcmp ( path, folder ))
		{
			gtk_list_store_prepend ( e -> history_back, & iter ) ;
			gtk_list_store_set ( e -> history_back, & iter, 0, folder, -1 ) ;
	
			g_free ( path ) ;
		}
	}
	
	gtk_list_store_clear ( e -> store ) ;
	gint update = 0 ;
	
	gchar * name = g_dir_read_name ( dir ) ;
	while ( name )
	{
		if ( timestamp != e -> timestamp )
			break ;
		
		if ( name [0] == '.' )
		{
			name = g_dir_read_name ( dir ) ;
			continue ;
		}
		
		gchar * full_name = g_build_filename ( folder, name, null ) ;
		
		GtkTreeIter iter ;
		GdkPixbuf * p = fm_get_icon ( full_name ) ;
		
		gtk_list_store_append ( e -> store, & iter ) ;
		gtk_list_store_set ( e -> store, & iter, 0, p, 1, name, 2, full_name, -1 ) ;
		
		if ( p != null )
			g_object_unref ( p ) ;
			
		g_free ( full_name ) ;
		name = g_dir_read_name ( dir ) ;
		
		update ++ ;
		if ( update > 50 )
		{
			april_update_gui () ;
			update = 0 ;
		}
		
		
	}

	g_dir_close ( dir ) ;
	explorer_wait_anim_stop ( e ) ;
}

gint fm_get_id ( const gchar * filename )
{
	gint i = 0, length = strlen ( filename ), id = 0 ;
	for ( i = 1 ; i < length ; i ++ ) // 0 is "."
	{
		id = id + ( gint ) filename [i] ;
	}
	
	return id ;
}

FileType fm_get_file_type ( const gchar * filename )
{
	if ( g_file_test ( filename, G_FILE_TEST_IS_DIR ))
		return FOLDER ;
	
	gchar * ext = g_strrstr ( filename, "." ) ;
	if ( ext == null )
		return UNKNOWN ;
	
	gint id = fm_get_id ( ext ) ;
	
	switch ( id )
	{
		case 320:
		case 314:
		case 346:
		case 273:
		case 266:
		case 378:
		case 328:
		case 223:
			return VIDEO ;
		
		case 334:
		case 272:
		case 317:
		case 247:
		case 406:
			return AUDIO ;
		
		case 321:
		case 422:
		case 319:
		case 310:
		case 325:
			return IMAGE ;
		
		case 352:
		case 332:
		//case 310:
			return TEXT ;
		
		case 437:
		case 329:
			return HTML ;
		
		default:
			return UNKNOWN ;
	}
}


GtkIconSize FM_ICON_SIZE_DEFAULT = 32 ;

GdkPixbuf * fm_get_icon ( gchar * filename )
{
	if ( FM_ICON_SIZE_DEFAULT == 0 )
		return null ;
	
	FileType t = fm_get_file_type ( filename ) ;
	GdkPixbuf * pixbuf = null ;
	
	switch ( t )
	{
		case AUDIO:
			pixbuf = panel_menu_find_icon ( "gnome-mime-audio", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case VIDEO:
			pixbuf = panel_menu_find_icon ( "gnome-mime-video", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case IMAGE:
			pixbuf = panel_menu_find_icon ( "gnome-mime-image", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case TEXT:
			pixbuf = panel_menu_find_icon ( "gnome-mime-text", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case HTML:
			pixbuf = panel_menu_find_icon ( "gnome-mime-text-html", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case FOLDER:
			pixbuf = panel_menu_find_icon ( "gtk-directory", FM_ICON_SIZE_DEFAULT ) ;
			break ;
		case UNKNOWN:
		default:
			pixbuf = panel_menu_find_icon ( "gtk-file", FM_ICON_SIZE_DEFAULT ) ;
			break ;
	}
	
	return pixbuf ;
}


GtkMenu * fm_create_menu_file ( Explorer * e )
{
	GtkMenu * menu = fm_create_menu_context_file ( e ) ;
	GtkMenuItem	* work_offline = gtk_check_menu_item_new_with_label ( "Work Offline" ),
				* close = gtk_menu_item_new_with_label ( "Close" ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	g_signal_connect_swapped ( close, "activate", gtk_widget_destroy, e -> window ) ;
	
	gtk_menu_shell_append ( menu, work_offline ) ;
	gtk_menu_shell_append ( menu, close ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_edit ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem	* undo_copy = gtk_menu_item_new_with_label ( "Undo Copy" ),
				* cut = gtk_menu_item_new_with_label ( "Cut" ),
				* copy = gtk_menu_item_new_with_label ( "Copy" ),
				* paste = gtk_menu_item_new_with_label ( "Paste" ),
				* paste_shortcut = gtk_menu_item_new_with_label ( "Paste Shortcut" ),
				* select_all = gtk_menu_item_new_with_label ( "Select All" ),
				* invert_selection = gtk_menu_item_new_with_label ( "Invert Selection" ) ;
				
	g_signal_connect_swapped ( select_all, "activate", fm_select_all, e ) ;
	g_signal_connect_swapped ( invert_selection, "activate", fm_invert_selection, e ) ;
	
	g_signal_connect_swapped ( cut, "activate", explorer_cut_callback, e ) ;
	g_signal_connect_swapped ( copy, "activate", explorer_copy_callback, e ) ;

	g_signal_connect_swapped ( paste, "activate", explorer_paste_from_clipboard, e ) ;
	g_signal_connect_swapped ( paste_shortcut, "activate", explorer_paste_shortcut, e ) ;
	
	g_signal_connect_swapped ( undo_copy, "activate", explorer_delete_from_clipboard, e ) ;
	
	gtk_menu_shell_append ( menu, undo_copy ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, cut ) ;
	gtk_menu_shell_append ( menu, copy ) ;
	gtk_menu_shell_append ( menu, paste ) ;
	gtk_menu_shell_append ( menu, paste_shortcut ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, select_all ) ;
	gtk_menu_shell_append ( menu, invert_selection ) ;

	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_view ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem	* toolbars = gtk_menu_item_new_with_label ( "Toolbars" ),
				* statusbar = gtk_check_menu_item_new_with_label ( "Status Bar" ),
	//			* explorerbar = gtk_menu_item_new_with_label ( "Explorer Bar" ),
				* as_web_page = gtk_check_menu_item_new_with_label ( "as Web Page" ),
				* arrange_icons = gtk_menu_item_new_with_label ( "Arrange Icons" ),
				* line_up_icons = gtk_menu_item_new_with_label ( "Line Up Icons" ),
				* refresh = gtk_menu_item_new_with_label ( "Refresh" ),
				* folder_options1 = gtk_menu_item_new_with_label ( "Folder Options..." ) ;

	GSList * l = null ;
	
	GtkRadioMenuItem * large = gtk_radio_menu_item_new_with_label ( null, "Large Icons" ),
					 * small = gtk_radio_menu_item_new_with_label ( gtk_radio_menu_item_get_group ( large ), "Small" ),
					 * list = gtk_radio_menu_item_new_with_label ( gtk_radio_menu_item_get_group ( small ), "List" ),
					 * details = gtk_radio_menu_item_new_with_label (  gtk_radio_menu_item_get_group ( list ), "Details" ) ;
	
	GtkMenu * t = gtk_menu_new () ;
	GtkMenuItem * m = gtk_check_menu_item_new_with_label ( "Main toolbar" ) ;
	
	gtk_menu_item_set_submenu ( toolbars, t ) ;
	gtk_menu_shell_append ( t, m ) ;
	
	gtk_check_menu_item_set_active ( m, GTK_WIDGET_VISIBLE ( e -> toolbar )) ;
	g_signal_connect ( m, "activate", _hide_unhide_components_by_menu, e -> toolbar ) ;
	
	gtk_check_menu_item_set_active ( statusbar, GTK_WIDGET_VISIBLE ( e -> statusbar )) ;
	g_signal_connect ( statusbar, "activate", _hide_unhide_components_by_menu, e -> statusbar ) ;
	
	switch ( FM_ICON_SIZE_DEFAULT )
	{
		default:
		case 32:
			gtk_check_menu_item_set_active ( large, on ) ;
			break ;
		case 24:
			gtk_check_menu_item_set_active ( small, on ) ;
			break ;
		case 16:
			gtk_check_menu_item_set_active ( list, on ) ;
			break;
		case 0:
			gtk_check_menu_item_set_active ( details, on ) ;
			break ;
	}
	
	g_signal_connect_swapped ( large, "activate", fm_switch_icon_size_default, e ) ;
	g_signal_connect_swapped ( small, "activate", fm_switch_icon_size_small, e ) ;
	g_signal_connect_swapped ( list, "activate", fm_switch_icon_size_list, e ) ;
	g_signal_connect_swapped ( details, "activate", fm_switch_icon_size_details, e ) ;

	g_signal_connect_swapped ( arrange_icons, "activate", fm_refresh, e ) ;
	g_signal_connect_swapped ( line_up_icons, "activate", fm_refresh, e ) ;
	
	g_signal_connect_swapped ( refresh, "activate", fm_refresh, e ) ;
	g_signal_connect_swapped ( folder_options1, "activate", folder_options, e ) ;
	
	gtk_menu_shell_append ( menu, toolbars ) ;
	gtk_menu_shell_append ( menu, statusbar ) ;
	//gtk_menu_shell_append ( menu, explorerbar ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, as_web_page ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, large ) ;
	gtk_menu_shell_append ( menu, small ) ;
	gtk_menu_shell_append ( menu, list ) ;
	gtk_menu_shell_append ( menu, details ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, arrange_icons ) ;
	gtk_menu_shell_append ( menu, line_up_icons ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, refresh ) ;
	gtk_menu_shell_append ( menu, folder_options1 ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_go ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * back = gtk_menu_item_new_with_label ( "Back" ),
				* forward = gtk_menu_item_new_with_label ( "Forward" ),
				* up = gtk_menu_item_new_with_label ( "Up One Level" ),
				* home = gtk_menu_item_new_with_label ( "Home Page" ),
//				* channel_guide = gtk_menu_item_new_with_label ( "Channel Guide" ),
//				* search = gtk_menu_item_new_with_label ( "Search the Web" ),
				* computer = gtk_menu_item_new_with_label ( "My Computer" ) ;
//				* address_book = gtk_menu_item_new_with_label ( "Address Book" ),
//				* internet_call = gtk_menu_item_new_with_label ( "Internet Call" ) ;
	
	g_signal_connect_swapped ( back, "activate", fm_go_back, e ) ;
	g_signal_connect_swapped ( forward, "activate", fm_go_forward, e ) ;
	
	g_signal_connect_swapped ( up, "activate", fm_go_up, e ) ;
	g_signal_connect_swapped ( home, "activate", fm_go_home, e ) ;
	
	gtk_menu_shell_append ( menu, back ) ;
	gtk_menu_shell_append ( menu, forward ) ;
	gtk_menu_shell_append ( menu, up ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, computer ) ;
	gtk_menu_shell_append ( menu, home ) ;
//	gtk_menu_shell_append ( menu, channel_guide ) ;
//	gtk_menu_shell_append ( menu, search ) ;
	
//	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
//	gtk_menu_shell_append ( menu, address_book ) ;
//	gtk_menu_shell_append ( menu, internet_call ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_favorites ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * add = gtk_menu_item_new_with_label ( "Add to Favorites" ),
				* delete = gtk_menu_item_new_with_label ( "Organize Favorites" ) ;
	
	e -> favorites = menu ;
	
	g_signal_connect_swapped ( add, "activate", fm_add_favorite, e ) ;
	g_signal_connect_swapped ( delete, "activate", favorites_organize, e ) ;
	
	gtk_menu_shell_append ( menu, add ) ;
	gtk_menu_shell_append ( menu, delete ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	favorites_create_menu ( e, menu ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_help ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * help = gtk_menu_item_new_with_label ( "Help" ),
				* about = gtk_menu_item_new_with_label ( "About April beta" ) ;
				
	gtk_menu_shell_append ( menu, help ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, about ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_context_folder ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * view = gtk_menu_item_new_with_label ( "View" ),
				* arrange_icons = gtk_menu_item_new_with_label ( "Arrange Icons" ),
				* line_up_icons = gtk_menu_item_new_with_label ( "Line Up Icons" ),
				* refresh = gtk_menu_item_new_with_label ( "Refresh" ),
				* paste = gtk_menu_item_new_with_label ( "Paste" ),
				* paste_shortcut = gtk_menu_item_new_with_label ( "Paste Shortcut" ),
				* undo_copy = gtk_menu_item_new_with_label ( "Undo Copy" ),
				* new = gtk_menu_item_new_with_label ( "New" ),
				* properties = gtk_menu_item_new_with_label ( "Properties" ) ;
	
	GtkMenu * new_menu = gtk_menu_new () ;
	GtkMenuItem * new_file = gtk_menu_item_new_with_label ( "Empty file" ),
				* new_folder = gtk_menu_item_new_with_label ( "New Folder" ) ;
	
	gtk_menu_shell_append ( new_menu, new_folder ) ;
	gtk_menu_shell_append ( new_menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( new_menu, new_file ) ;
	
	g_signal_connect_swapped ( new_file, "activate", fm_new_file, e ) ;
	g_signal_connect_swapped ( new_folder, "activate", fm_new_folder, e ) ;
	
	g_signal_connect_swapped ( properties, "activate", explorer_file_info, e ) ;
	gtk_menu_item_set_submenu ( new, new_menu ) ;
	
	GtkMenu * submenu = gtk_menu_new () ;
	GtkRadioMenuItem * large = gtk_radio_menu_item_new_with_label ( null, "Large Icons" ),
					 * small = gtk_radio_menu_item_new_with_label ( gtk_radio_menu_item_get_group ( large ), "Small" ),
					 * list = gtk_radio_menu_item_new_with_label ( gtk_radio_menu_item_get_group ( small ), "List" ),
					 * details = gtk_radio_menu_item_new_with_label (  gtk_radio_menu_item_get_group ( list ), "Details" ) ;
	
	GtkMenu * view_menu = gtk_menu_new () ;
	GtkMenuItem * menubar = gtk_check_menu_item_new_with_label ( "Menu bar" ),
				* toolbar = gtk_check_menu_item_new_with_label ( "Tool bar" ),
				* statusbar = gtk_check_menu_item_new_with_label ( "Status bar" ) ;
	
	switch ( FM_ICON_SIZE_DEFAULT )
	{
		default:
		case 32:
			gtk_check_menu_item_set_active ( large, on ) ;
			break ;
		case 24:
			gtk_check_menu_item_set_active ( small, on ) ;
			break ;
		case 16:
			gtk_check_menu_item_set_active ( list, on ) ;
			break;
		case 0:
			gtk_check_menu_item_set_active ( details, on ) ;
			break ;
	}
	
	gtk_check_menu_item_set_active ( menubar, GTK_WIDGET_VISIBLE ( e -> menubar )) ;
	gtk_check_menu_item_set_active ( toolbar, GTK_WIDGET_VISIBLE ( e -> toolbar )) ;
	
	gtk_check_menu_item_set_active ( statusbar, GTK_WIDGET_VISIBLE ( e -> statusbar )) ;
	
	g_signal_connect ( menubar, "activate", _hide_unhide_components_by_menu, e -> menubar ) ;
	g_signal_connect ( statusbar, "activate", _hide_unhide_components_by_menu, e -> statusbar ) ;
	
	g_signal_connect ( toolbar, "activate", _hide_unhide_components_by_menu, e -> toolbar ) ;
	
	g_signal_connect_swapped ( large, "activate", fm_switch_icon_size_default, e ) ;
	g_signal_connect_swapped ( small, "activate", fm_switch_icon_size_small, e ) ;
	g_signal_connect_swapped ( list, "activate", fm_switch_icon_size_list, e ) ;
	g_signal_connect_swapped ( details, "activate", fm_switch_icon_size_details, e ) ;
	
	g_signal_connect_swapped ( line_up_icons, "activate", fm_refresh, e ) ;
	g_signal_connect_swapped ( refresh, "activate", fm_refresh, e ) ;
	
	g_signal_connect_swapped ( paste, "activate", explorer_paste_from_clipboard, e ) ;
	g_signal_connect_swapped ( paste_shortcut, "activate", explorer_paste_shortcut, e ) ;
	
	g_signal_connect_swapped ( undo_copy, "activate", explorer_delete_from_clipboard, e ) ;
	
	gtk_menu_shell_append ( view_menu, menubar ) ;
	gtk_menu_shell_append ( view_menu, toolbar ) ;
	
	gtk_menu_shell_append ( view_menu, gtk_separator_menu_item_new ()) ;
	gtk_menu_shell_append ( view_menu, statusbar ) ;
	
	gtk_menu_shell_append ( submenu, large ) ;
	gtk_menu_shell_append ( submenu, small ) ;
	gtk_menu_shell_append ( submenu, list ) ;
	gtk_menu_shell_append ( submenu, details ) ;
	
	gtk_menu_shell_append ( menu, view ) ;
	gtk_menu_item_set_submenu ( view, view_menu ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, arrange_icons ) ;
	gtk_menu_shell_append ( menu, line_up_icons ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	gtk_menu_shell_append ( menu, refresh ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, paste ) ;
	gtk_menu_shell_append ( menu, paste_shortcut ) ;
	
	gtk_menu_shell_append ( menu, undo_copy ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, new ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, properties ) ;
	gtk_menu_item_set_submenu ( arrange_icons, submenu ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_send_to ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	gint i = 0 ;
	
	for ( i = 1 ; i < SEND_TO_NONE ; i ++ )
	{
		GtkMenuItem * item = gtk_menu_item_new_with_label ( send_to_targets [i] ) ;
		Sendto * sendto = sendto_new ( e, i ) ;
		
		g_signal_connect ( item, "activate", explorer_send_to, sendto ) ;
		gtk_menu_shell_append ( menu, item ) ;
	}
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}


GtkMenu * fm_create_menu_context_file ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * open = gtk_menu_item_new_with_label ( "Open" ),
				* open_with = gtk_menu_item_new_with_label ( "Open with ,,," ),
				* send_to = gtk_menu_item_new_with_label ( "Send To" ),
				* cut = gtk_menu_item_new_with_label ( "Cut" ),
				* copy = gtk_menu_item_new_with_label ( "Copy" ),
				* link = gtk_menu_item_new_with_label ( "Create Shortcut" ),
				* delete = gtk_menu_item_new_with_label ( "Delete" ),
				* rename = gtk_menu_item_new_with_label ( "Rename" ),
				* properties = gtk_menu_item_new_with_label ( "Properties" ) ;
	
	GtkMenu * send = fm_create_menu_send_to ( e ) ;
	gtk_menu_item_set_submenu ( send_to, send ) ;
	
	g_signal_connect_swapped ( open, "activate", _explorer_activate, e ) ;
	g_signal_connect_swapped ( open_with, "activate", explorer_open_with, e ) ;
				
	g_signal_connect_swapped ( cut, "activate", explorer_cut_callback, e ) ;
	g_signal_connect_swapped ( copy, "activate", explorer_copy_callback, e ) ;

	g_signal_connect_swapped ( link, "activate", explorer_create_shortcut, e ) ;
	g_signal_connect_swapped ( delete, "activate", explorer_delete_selected_files, e ) ;

	g_signal_connect_swapped ( rename, "activate", explorer_rename, e ) ;
	g_signal_connect_swapped ( properties, "activate", explorer_file_info, e ) ;
	
	gtk_menu_shell_append ( menu, open ) ;
	gtk_menu_shell_append ( menu, open_with ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, send_to ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, cut ) ;
	gtk_menu_shell_append ( menu, copy ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, link ) ;
	gtk_menu_shell_append ( menu, delete ) ;
	
	gtk_menu_shell_append ( menu, rename ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, properties ) ;
	gtk_widget_show_all ( menu ) ;
	
	return menu ;
}


GtkMenu * fm_create_menu_context_desktop ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * active_desktop = gtk_menu_item_new_with_label ( "Active Desktop" ),
				* arrange_icons = gtk_menu_item_new_with_label ( "Arrange Icons" ),
				* line_up_icons = gtk_menu_item_new_with_label ( "Line Up Icons" ),
				* refresh = gtk_menu_item_new_with_label ( "Refresh" ),
				* paste = gtk_menu_item_new_with_label ( "Paste" ),
				* paste_shortcut = gtk_menu_item_new_with_label ( "Paste Shortcut" ),
				* undo_copy = gtk_menu_item_new_with_label ( "Undo Copy" ),
				* new = gtk_menu_item_new_with_label ( "New" ),
				* properties = gtk_menu_item_new_with_label ( "Properties" ) ;
	
	gtk_menu_shell_append ( menu, active_desktop ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, arrange_icons ) ;
	gtk_menu_shell_append ( menu, line_up_icons ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	gtk_menu_shell_append ( menu, refresh ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, paste ) ;
	gtk_menu_shell_append ( menu, paste_shortcut ) ;
	
	gtk_menu_shell_append ( menu, undo_copy ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, new ) ;
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, properties ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

GtkMenu * fm_create_menu_context_desktop_file ( Explorer * e )
{
	GtkMenu * menu = gtk_menu_new () ;
	GtkMenuItem * open = gtk_menu_item_new_with_label ( "Open" ),
				* explore = gtk_menu_item_new_with_label ( "Explore" ),
				* remove_from_desktop = gtk_menu_item_new_with_label ( "Remove from Desktop" ),
				* create_shortcut = gtk_menu_item_new_with_label ( "Create Shortcut" ),
				* rename = gtk_menu_item_new_with_label ( "Rename" ),
				* properties = gtk_menu_item_new_with_label ( "Properties" ) ;
	
	gtk_menu_shell_append ( menu, open ) ;
	gtk_menu_shell_append ( menu, explore ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	
	gtk_menu_shell_append ( menu, create_shortcut ) ;
	gtk_menu_shell_append ( menu, rename ) ;
	
	gtk_menu_shell_append ( menu, gtk_separator_menu_item_new ()) ;
	gtk_menu_shell_append ( menu, properties ) ;
	
	gtk_widget_show_all ( menu ) ;
	return menu ;
}

void fm_go_back ( Explorer * e )
{
	explorer_fire_event ( e ) ;
	
	if ( gtk_tree_model_iter_n_children ( e -> history_back, null ) == 0 )
		g_debug ( "%s: No destination available", __func__ ) ;
	else
	{
		gchar * path = null ;
		GtkTreeIter iter, iter1 ;
		
		gtk_tree_model_get_iter_first ( e -> history_back, & iter ) ;
		gtk_tree_model_get ( e -> history_back, & iter, 0, & path, -1 ) ;
		
		fm_open ( e, path ) ;
		
		gtk_list_store_prepend ( e -> history_forward, & iter1 ) ;
		gtk_list_store_set ( e -> history_forward, & iter1, 0, path, -1 ) ;
		
		gtk_list_store_remove ( e -> history_back, & iter ) ;
		g_free ( path ) ;
	}
}

void fm_go_forward ( Explorer * e )
{
	explorer_fire_event ( e ) ;
	
	if ( gtk_tree_model_iter_n_children ( e -> history_forward, null ) == 0 )
		g_debug ( "%s: No destination available", __func__ ) ;
	else
	{
		gchar * path = null ;
		GtkTreeIter iter ;
		
		gtk_tree_model_get_iter_first ( e -> history_forward, & iter ) ;
		gtk_tree_model_get ( e -> history_forward, & iter, 0, & path, -1 ) ;
		
		fm_open ( e, path ) ;
		g_free ( path ) ;
		
		gtk_list_store_remove ( e -> history_forward, & iter ) ;
	}
}

void fm_go_up ( Explorer * e )
{
	explorer_fire_event ( e ) ;

	// This is as high as we can go
	gchar * current = explorer_get_current_folder ( e ) ;
	if ( strcmp ( current, "/" ) == 0 )
	{
		g_free ( current ) ;
		return ;
	}
	
	gchar * up = g_path_get_dirname ( current ) ;
	
	if ( up [0] == '.' )
		fm_open ( e, "/" ) ;
	else
		fm_open ( e, up ) ;
	
	g_free ( current ) ;
	g_free ( up ) ;
}

void fm_icon_view_activated ( GtkWidget * icon_view, GtkTreePath * path, Explorer * e )
{
	GtkTreeIter iter ;
	gtk_tree_model_get_iter ( e -> store, & iter, path ) ;
	
	gchar * filename = null ;
	gtk_tree_model_get ( e -> store, & iter, 2, & filename, -1 ) ;
	
	mime_handler ( e, filename ) ;
	g_free ( filename ) ;
}

void fm_refresh ( Explorer * e )
{
	gchar * path = explorer_get_current_folder ( e ) ;
	fm_open ( e, path ) ;
	
	g_free ( path ) ;
}

void fm_append_to_store ( Explorer * e, gchar * filename )
{
	GtkTreeIter iter ;
	GdkPixbuf * p = fm_get_icon ( filename ) ;
	
	gchar * name = g_path_get_basename ( filename ) ;
	
	gtk_list_store_append ( e -> store, & iter ) ;
	gtk_list_store_set ( e -> store, & iter, 0, p, 1, name, 2, filename, -1 ) ;
	
	g_free ( name ) ;
	g_object_unref ( p ) ;
		
}

gboolean fm_handle_context_menu ( GtkWidget * widget, GdkEventButton * event, Explorer * e )
{
	/* Single click mode */
	if ( e -> config.click_mode == 1 && event -> button == 1 )
	{
		gtk_icon_view_unselect_all ( e -> iconview ) ;
		
		gint x = 0, y = 0 ;
		gtk_widget_get_pointer ( gtk_widget_get_parent ( widget ), & x, & y ) ;
		
		gdouble adj = 0.0 ;
		GtkAdjustment * adjustment = gtk_scrolled_window_get_vadjustment ( gtk_widget_get_parent ( widget )) ;
	
		adj = gtk_adjustment_get_value ( adjustment ) ;
		y = y + ( gint32 ) adj ;
				
		GtkTreePath * path = gtk_icon_view_get_path_at_pos ( widget, x, y ) ;
		if ( path == null )
			return false ;

		gtk_icon_view_select_path ( widget, path ) ;
		gtk_tree_path_free ( path ) ;

		gint u = 0 ;
		for ( u = 0 ; u < 10 ; u ++ )
		{
			g_usleep ( 1000 ) ;
			april_update_gui () ;
		}
		
		_explorer_activate ( e ) ;
		return true ;
	}

	if ( event -> button != 3 )
		return false ;
	
	/********************************************/
	
	gint x = 0, y = 0 ;
	gtk_widget_get_pointer ( gtk_widget_get_parent ( widget ), & x, & y ) ;
	
	gdouble adj = 0.0 ;
	GtkAdjustment * adjustment = gtk_scrolled_window_get_vadjustment ( gtk_widget_get_parent ( widget )) ;

	adj = gtk_adjustment_get_value ( adjustment ) ;
	y = y + ( gint32 ) adj ;
			
	GtkTreePath * path = gtk_icon_view_get_path_at_pos ( widget, x, y ) ;
	if ( path == null )
	{
		gtk_icon_view_unselect_all ( widget ) ;

		GtkMenu * menu = fm_create_menu_context_folder ( e ) ;
		g_signal_connect ( menu, "selection-done", gtk_widget_destroy, null ) ;
		
		gtk_menu_popup ( menu, null, null, null, null, 3, gtk_get_current_event_time ()) ;
		return true;
	}
	else
	{
		gtk_icon_view_select_path ( widget, path ) ;
		gtk_tree_path_free ( path ) ;
		
		GtkMenu * menu = fm_create_menu_context_file ( e ) ;
		g_signal_connect ( menu, "selection-done", gtk_widget_destroy, null ) ;
		
		gtk_menu_popup ( menu, null, null, null, null, 3, gtk_get_current_event_time ()) ;
		return true;
	}

	/**************************************************/
	return false ;
}

Sendto * sendto_new ( Explorer * e, SendtoTargets target )
{
	GMemChunk * mem = g_mem_chunk_create ( Sendto, 10, G_ALLOC_ONLY ) ;
	Sendto * sendto = g_chunk_new ( Sendto, mem ) ;
	
	sendto -> e = e ;
	sendto -> target = target ;
	
	sendto -> memory = mem ;
	return sendto ;
}
	
void sendto_destroy ( Sendto * sendto )
{
	g_mem_chunk_destroy ( sendto -> memory ) ;
}

gboolean fm_pop_menu ( GtkWidget * widget, GdkEventKey * event, Explorer * e )
{
	GList * l = gtk_icon_view_get_selected_items ( e -> iconview ) ;
	gboolean s = g_list_length ( l ) ;
	
	g_list_foreach ( l, gtk_tree_path_free, null ) ;
	g_list_free ( l ) ;
	
	if ( ! s )
	{
		GtkMenu * menu = fm_create_menu_context_folder ( e ) ;
		g_signal_connect ( menu, "selection-done", gtk_widget_destroy, null ) ;
		
		gtk_menu_popup ( menu, null, null, null, null, 3, gtk_get_current_event_time ()) ;
		return true;
	}
	else
	{
		GtkMenu * menu = fm_create_menu_context_file ( e ) ;
		g_signal_connect ( menu, "selection-done", gtk_widget_destroy, null ) ;
		
		gtk_menu_popup ( menu, null, null, null, null, 3, gtk_get_current_event_time ()) ;
		return true;
	}
}	

void _hide_unhide_components_by_menu ( GtkWidget * widget, GtkWidget * component )
{
	if ( gtk_check_menu_item_get_active ( widget ))
		gtk_widget_show ( component ) ;
	else
		gtk_widget_hide ( component ) ;
}

void fm_switch_icon_size_small ( Explorer * e )
{
	FM_ICON_SIZE_DEFAULT = 24 ;
	gtk_icon_view_set_orientation ( e -> iconview, GTK_ORIENTATION_VERTICAL ) ;
	
	fm_refresh ( e ) ;
}

void fm_switch_icon_size_list ( Explorer * e )
{
	FM_ICON_SIZE_DEFAULT = 16 ;
	gtk_icon_view_set_orientation ( e -> iconview, GTK_ORIENTATION_HORIZONTAL ) ;
	
	fm_refresh ( e ) ;
}

void fm_switch_icon_size_details ( Explorer * e )
{
	FM_ICON_SIZE_DEFAULT = 0 ;
	gtk_icon_view_set_orientation ( e -> iconview, GTK_ORIENTATION_HORIZONTAL ) ;
	
	fm_refresh ( e ) ;
}

void fm_switch_icon_size_default ( Explorer * e )
{
	FM_ICON_SIZE_DEFAULT = 32 ;
	gtk_icon_view_set_orientation ( e -> iconview, GTK_ORIENTATION_VERTICAL ) ;
	
	fm_refresh ( e ) ;
}

void fm_new_folder ( Explorer * e )
{
	gchar * name = prompt_get_string ( "New folder", "Type the name of new folder" ) ;
	if ( name == null )
		return ;
	
	gchar * parent = explorer_get_current_folder ( e ) ;
	gchar * filename = g_build_filename ( parent, name, null ) ;
	
	if ( g_mkdir_with_parents ( filename, 0700 ))
		g_critical ( "Cannot create folder: %s", strerror ( errno )) ;
	else
		fm_append_to_store ( e, filename ) ;
	
	g_free ( parent ) ;
	g_free ( filename ) ;
	
	g_free ( name ) ;
}

void fm_new_file ( Explorer * e )
{
	gchar * name = prompt_get_string ( "Empty file", "Type the name of new empty file" ) ;
	if ( name == null )
		return ;
	
	gchar * parent = explorer_get_current_folder ( e ) ;
	gchar * filename = g_build_filename ( parent, name, null ) ;
	
	File * fp = fopen ( filename, "w" ) ;
	if ( fp == null )
		g_critical ( "Cannot create file: %s", strerror ( errno )) ;
	else
	{
		fclose ( fp ) ;
		fm_append_to_store ( e, filename ) ;
	}
	
	g_free ( parent ) ;
	g_free ( filename ) ;
	
	g_free ( name ) ;
}

void fm_select_all ( Explorer * e )
{
	gtk_icon_view_select_all ( e -> iconview ) ;
}

vodi fm_invert_selection ( Explorer * e )
{
	gtk_icon_view_select_all ( e -> iconview ) ;
	
	GList * list = gtk_icon_view_get_selected_items ( e -> iconview ) ;
	gint i = 0, len = g_list_length ( list ) ;
	
	for ( i = 0 ; i < len ; i ++ )
	{
		gtk_icon_view_unselect_path ( e -> iconview,
				g_list_nth_data ( list, i )) ;
	}
	
	g_list_foreach ( list, gtk_tree_path_free, null ) ;
	g_list_free ( list ) ;
}
	
void fm_go_home ( Explorer * e )
{
	fm_open ( e, g_get_home_dir ()) ;
}

void fm_add_favorite ( Explorer * e )
{
	gchar * file = explorer_get_current_folder ( e ) ;
	favorites_add ( e, file ) ;
	
	g_free ( file ) ;
}

